/*
PARI/GP scripts for primes-related functions 
=============================================================
File: PrimesRelatedFunctions.txt    
Link: https://oeis.org/wiki/File:PrimesRelatedFunctions.txt
=============================================================
*/

IsNotPrime(n) = !isprime(n);
IsOddButNotPrime(n) = (n%2) && (!isprime(n));

PreviousIsPrime(n) = isprime(n-1);
NextIsPrime(n) = isprime(n+1);
IsTwinPrime(n) = isprime(n) && (isprime(n-2)||isprime(n+2));

IsLowerOfTwinPrimes(n) = isprime(n) && isprime(n+2);
IsUpperOfTwinPrimes(n) = isprime(n) && isprime(n-2);
IsBetweenTwinPrimes(n) = isprime(n+1) && isprime(n-1);
IsNeighbourOfPrime(n)  = n && (isprime(n+1) || isprime(n-1));

IsBiPrime(n)    = bigomega(n)==2;
IsTriPrime(n)   = bigomega(n)==3;
IsTetraPrime(n) = bigomega(n)==4;
IsPentaPrime(n) = bigomega(n)==5;

Has2DistinctPrimeFactors(n) = omega(n)==2;
Has3DistinctPrimeFactors(n) = omega(n)==3;
Has4DistinctPrimeFactors(n) = omega(n)==2;
Has5DistinctPrimeFactors(n) = omega(n)==3;

OmegaDivBigomega(n) = bigomega(n)%omega(n)==0;
OmegaPropDivBigomega(n) = 
  (bigomega(n)>omega(n))&&(bigomega(n)%omega(n)==0);

IsMoebiusMinus1(n)  = moebius(n)==-1;
IsMoebiusPlus1(n)   = moebius(n)== 1;
IsMoebiusZero(n)    = moebius(n)== 0;
IsMoebiusNonZero(n) = moebius(n)!= 0;

IsSqrtPrime(n) = isprime(sqrtint(n));
IsPwrPrime(n,realp) = isprime(floor(n^realp));


LargestPrimeFactor(n) =
/* ----------------------------------------------------------
  For n >1 returns the largest prime factor of n.
  For n<=1 returns n.
---------------------------------------------------------- */
{
  if (n<=1,return(n));
  my (v=factor(n));
  return (v[#v[,1],1]);
}

SumOfPrimeFactors(n) =
/* ----------------------------------------------------------
  Returns the sum of prime factors of n, with multiplicity.
  For n<=1 returns 0.
  Generates A001414. 
---------------------------------------------------------- */
{
  if (n<=1,return(0));
  my (v=factor(n));
  sum(k=1,#v[,1],v[k,1]*v[k,2]);
}

SumOfPrimeFactorsN(n) =
/* ----------------------------------------------------------
  Returns the sum of prime factors of n, (no multiplicity).
  For n<=1 returns 0.
  Generates A001414. 
---------------------------------------------------------- */
{
  if (n<=1,return(0));
  my (v=factor(n));
  sum(k=1,#v[,1],v[k,1]);
}

ProductOfPrimeFactorsN(n) =
/* ----------------------------------------------------------
  Return the product of prime divisors of n (no multiplicity).
  Also known as the largest square-free kernel of n,
  or the radical of n, rad(n).
  For n<=1 returns 1.
  Generates A007947.
---------------------------------------------------------- */
{
  if (n<=1,return(1));
  my (v=factor(n));
  prod(k=1,#v[,1],v[k,1]);
}

PreviousPrime(n) = if (n<=2,n,precprime(n-1));
/* ----------------------------------------------------------
  For n >2 returns the largest prime smaller than n.
  For n<=2 returns n, differentiating it from precprime(n-1).
---------------------------------------------------------- */

FollowingPrime(n) = if (n<2,n,nextprime(n+1));
/* ----------------------------------------------------------
  For n >1 returns the smallest prime larger than n.
  For n==1 returns 1, differentiating it from nextprime(n+1).
---------------------------------------------------------- */

NumberOfNonCoprimes(n) = n-eulerphi(n)-1;
/* ----------------------------------------------------------
  Number of integers m, 1< m < n, which are not coprime to n
---------------------------------------------------------- */

IntervalPrimesProduct(m,n) =
/* ----------------------------------------------------------
  Product of all primes p in the interval (m,n].
  For the product of all primes up to n (primorial),
  set m=0 or m=1.
---------------------------------------------------------- */
{
  my (result=1);
  forprime (p=1+m, n, result*=p);
  return (result);
}

A233511(n) =
/* ----------------------------------------------------------
  Replaces the largest prime factor by the previous prime,
  unless it is 2 (or none) in which case does nothing.
  Used to generate OEIS A233511
---------------------------------------------------------- */
{
  my (p=LargestPrimeFactor(n));
  return ((n\p)*PreviousPrime(p));
}

A233570(n) =
/* ----------------------------------------------------------
  Replaces the smallest prime factor by the next prime.
  Used to generate OEIS A233570.
---------------------------------------------------------- */
{
  my (p=SmallestPrimeFactor(n));
  return ((n\p)*FollowingPrime(p));
}
 
Lambda(n) =
/* ----------------------------------------------------------
  Computes the central binomial(n,(n+1)\2),
  purged of all prime factors exceeding (n+1)\2.
  For the central binomial coefficient, set
  m=floor((n+1)\2) (OEIS A212791).
---------------------------------------------------------- */
{
  my (result=binomial(n,(n+1)\2));
  forprime(p=1+(n+1)\2,n,result/=p);
  return(result);
}

AltSum1DivPrimePwr(x,eps) =
/* ----------------------------------------------------------
Computes the running sum of the alternating-signs series
	C(x) = -Sum(k= 1,2,3,...)((-1)^k/p(k)^x),
where p(k) is the k-th prime.

The features using n, s, and sl consitute a running filter.
The filtered values have the same long-range convergence
properties as the original, brute-force running sum, but
suffer less from confusing "my" excursions. This facilitates
a visual estimate of the convergence behaviour. When running,
this function displays the current prime number index and the
corresponding filtered value of the sum.

To make sure that any published values are correct, proceed
as follows: set precision to 100 digits (\p 100) and call
AltSum1DivPrimePwr(x,1e-100). While the program is running,
observe the first digit D which changes by 1 about once
every 10 seconds. Consider as "likely stable" the digit D-3,
and as stable the one before it. Do not trust at all digits
D-1 and D-2 because they can still change after a few hours
of computation. Computing C(2) to 17 stable digits took
several days on a PC. However, reaching the same precision
for C(3) takes only tens of minutus; understandably, the
higher is the value of x, the faster is the convergence.
When you want to stop the computation, press Ctrl-C
and copy the stable digits.

Note: in principle, the function works with any positive
value of x; it does not have to be integer.

Note: further work on automating the task is desirable.

Used to compute A242301 - A242304, and test A078437.
---------------------------------------------------------- */
{
  my(n,k,sgn,p,i,s,sl,t,r);
  n  = 1000;
  s  = vector(n);
  sl = vector(n);
  k  = 0;
  sgn = -1.0;
  while (1,
    k += 1;
    sgn = -sgn;
    p = prime(k);
    t = sgn/p^x;
    s[1] = sl[1]+t;
    for (i=1,n-1,
      s[i+1] = 0.5*(s[i]+sl[i]);
      sl[i] = s[i];
    );
    if (k>n,
      print(k," ",0.5*(s[n]+sl[n]));
      if (abs(s[n]-s[n-1])<eps,break);
    ); 
    sl[n] = s[n];
  );
  return (0.5*(s[n]+sl[n]));  
}


/*
-------------------------------------------------------------
-------------------------------------------------------------
   Digit-based prime-related functions
-------------------------------------------------------------
-------------------------------------------------------------
   These need also the file DigitBasedFuntions.txt
*/


IsReversedPrime(n,b=10) = isprime(ReverseDigits(n,b));
/* ----------------------------------------------------------
  Boolean test: 
  The number with reversed digits must be a prime.
  The base argument b is optional (default = 10).
  Examples: 32 returns 1, 23 returns 0.
  See A095179.
---------------------------------------------------------- */

IsReversiblePrime(n,b=10) =
	(isprime(n) && isprime(ReverseDigits(n,b)));
/* ----------------------------------------------------------
  Boolean test: The number n must be a prime,
  and so must be the one with reversed digits.
  The base argument b is optional (default = 10).
  Examples: 13 returns 1, 23 returns 0.
  See A007500.
---------------------------------------------------------- */


/*
=============================================================
   Contributed to OEIS Wiki by Stanislav Sykora
=============================================================
*/
